package com.sz.common.core.system.service.impl;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.classic.spi.ThrowableProxyUtil;
import ch.qos.logback.core.CoreConstants;
import com.sz.common.base.logger.DbLoggingService;
import com.sz.common.base.service.AbstractService;
import com.sz.common.core.system.entity.SysLogging;
import org.springframework.stereotype.Service;

/**
 * Function: SysDbLoggingServiceImpl <br>
 * Author: Charles <br>
 * Date: 2016-11-30 14:02:00
 */
@Service("DbLoggingService")
public class SysDbLoggingServiceImpl extends AbstractService implements DbLoggingService {

    /**
     * 记录日志到数据库
     *
     * @param domainId      域Id
     * @param agentId       agentId
     * @param iLoggingEvent event
     */
    @Override
    public void logging(int domainId, String agentId, ILoggingEvent iLoggingEvent) {
        SysLogging logging = new SysLogging();
        logging.setTimestmp(iLoggingEvent.getTimeStamp());
        logging.setLoggerName(iLoggingEvent.getLoggerName());
        logging.setLevelString(iLoggingEvent.getLevel().levelStr);
        logging.setThreadName(iLoggingEvent.getThreadName());

        StackTraceElement[] traces = iLoggingEvent.getCallerData();
        if (traces != null && traces.length > 0 && traces[0] != null) {
            StackTraceElement caller = traces[0];
            logging.setCallerFilename(caller.getFileName());
            logging.setCallerClass(caller.getClassName());
            logging.setCallerMethod(caller.getMethodName());
            logging.setCallerLine(String.valueOf(caller.getLineNumber()));
        }

        logging.setAgentId(agentId);
        logging.setDomainId(domainId);

        StringBuilder content = new StringBuilder(iLoggingEvent.getFormattedMessage());
        if (iLoggingEvent.getThrowableProxy() != null) {
            String exceptions = buildExceptionMessage(iLoggingEvent.getThrowableProxy());
            content.append(exceptions);
        }
        logging.setFormattedMessage(content.toString());

        this.logging(logging);
    }

    private String buildExceptionMessage(IThrowableProxy tp) {
        StringBuilder text = new StringBuilder();
        while (tp != null) {
            text.append(buildOneExceptionMessage(tp));
            tp = tp.getCause();
        }
        return text.toString();
    }

    private String buildOneExceptionMessage(IThrowableProxy tp) {
        StringBuilder buf = new StringBuilder();
        ThrowableProxyUtil.subjoinFirstLine(buf, tp);

        int commonFrames = tp.getCommonFrames();
        StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
        for (int i = 0; i < stepArray.length - commonFrames; i++) {
            buf.append(CoreConstants.TAB);
            ThrowableProxyUtil.subjoinSTEP(buf, stepArray[i]);
        }
        if (commonFrames > 0) {
            buf.append(CoreConstants.TAB).append("... ").append(commonFrames).append(" common frames omitted");
        }
        return buf.toString();
    }

    public void logging(SysLogging logging) {
        if (logging == null) {
            throw new IllegalArgumentException("logging is empty");
        }
        this.dao.save(getSqlName("insertSelective"), logging);
    }

    @Override
    protected String getMapperNamespace() {
        return "com.sz.common.core.system.mapper.SysLoggingMapper";
    }
}
